﻿
using UnityEngine;

namespace XFGameFramework.OctreeSystem
{

    public class OctreePlane
    {
        #region 字段

        private Vector3 center;
        private Vector3 normal;
        [Tooltip("表示的是从中心的左边到中心右边的总宽度")]
        private float width;
        [Tooltip("表示的是从中心的下边到中心上边的总高度")]
        private float height;

        private Vector3 width_direction;
        private Vector3 height_direction;

        #endregion

        #region 属性

        public Vector3 Center => center;

        public Vector3 Normal => normal;

        public float Width => width;

        public float Height => height;

        public Vector3 WidthDirection => width_direction;

        public Vector3 HeightDirection => height_direction;

        #endregion

        #region 方法

        public void SetCenterAndNormal(Vector3 center, Vector3 normal, float width, float height, Vector3 width_direction, Vector3 height_direction)
        {
            this.center = center;
            this.normal = normal;
            this.width = width;
            this.height = height;
            this.width_direction = width_direction;
            this.height_direction = height_direction;
        }

        public void SetSize(float width, float height)
        {
            this.width = width;
            this.height = height;
        }

        public bool GetPoint(Ray ray, out Vector3 point, float distance = -1)
        {
            float angle = Vector3.Angle(ray.direction, this.normal);

            if (Vector3.Angle(ray.direction, this.normal) <= 90)
            {
                point = Vector3.zero;
                //Debug.LogFormat("角度不满足:{0}", Vector3.Angle(ray.direction, this.normal));
                return false;
            }

            // 判断射线是否有交点
            if (Vector3.Dot(ray.origin - Center, normal) <= 0)
            {
                // 说明射线的起点在平面下方 这样永远不可能有相交
                point = Vector3.zero;
                //Debug.LogFormat("射线位置不满足:{0}", Vector3.Dot(ray.origin - Center, normal));
                return false;
            }

            //float dis = Vector3.Distance(origin, des);
            float dis = Vector3.Distance(Center, ray.origin) * Mathf.Cos(Vector3.Angle(ray.origin - Center, Normal) * Mathf.Deg2Rad);

            //Debug.DrawLine(ray.origin, ray.origin - Normal * dis, Color.gray);

            angle = 180 - angle;

            float d = dis / Mathf.Cos(angle * Mathf.Deg2Rad);

            if (distance >= 0 && d >= distance)
            {
                point = Vector3.zero;
                //Debug.LogFormat("距离不满足:{0} distance:{1}", d, distance);
                return false;
            }

            point = ray.GetPoint(d);

            float center_distance = Vector3.Distance(point, center);
            Vector3 center_diection = (point - center).normalized;

            if (Mathf.Abs(Vector3.Dot(center_diection, WidthDirection)) * center_distance <= Width / 2 && Mathf.Abs(Vector3.Dot(center_diection, HeightDirection)) * center_distance <= Height / 2)
            {
                return true;
            }
            //else
            //{
            //    Debug.LogFormat("坐标不满足:{0} ", Mathf.Abs(Vector3.Dot(center_diection, WidthDirection)) * center_distance);
            //}

            return false;
        }


        public void Transform(Matrix4x4 matrix)
        {
            Vector3 new_center = matrix.MultiplyPoint(Center);
            Vector3 new_normal = matrix.MultiplyVector(Normal).normalized;

            Vector3 new_height_point = matrix.MultiplyPoint(Center + HeightDirection * height / 2);
            Vector3 new_width_point = matrix.MultiplyPoint(Center + WidthDirection * width / 2);

            Vector3 new_width_direction = (new_width_point - new_center).normalized;
            Vector3 new_height_direction = (new_height_point - new_center).normalized;

            float new_width = Vector3.Distance(new_width_point, new_center) * 2;
            float new_height = Vector3.Distance(new_height_point, new_center) * 2;

            center = new_center;
            normal = new_normal;
            width = new_width;
            height = new_height;
            width_direction = new_width_direction;
            height_direction = new_height_direction;
        }


        public Vector3 ClosestPoint(Vector3 point)
        {
            Vector3 center_direction = point - Center;

            float angle = (90 - Vector3.Angle(Normal, center_direction)) * Mathf.Deg2Rad;
            float distance = Mathf.Cos(angle) * Vector3.Distance(point, Center);
            Vector3 direction = Vector3.Cross(Vector3.Cross(center_direction, Normal), Normal).normalized;

            if (Vector3.Angle(center_direction, direction) > 90)
                direction = -direction;

            return Center + direction * distance;
        }

        public bool IntersectPoint(OctreePlane other, out Vector3 point)
        {
            point = Vector3.zero;


            float angle = Vector3.Angle(Normal, other.Normal);

            // 法线的角度接近于0 的时候 , 说明面与面平行 , 此时不存在交点
            if (angle < 0.01f || Mathf.Abs(angle - 180) < 0.01f)
                return false;

            Vector3 closest_point = ClosestPoint(other.Center);

            float closest_distance = Vector3.Distance(other.Center, closest_point);

            Vector3 closest_direction = other.Center - closest_point;

            float distance = Mathf.Tan((90 - Vector3.Angle(closest_direction, other.Normal)) * Mathf.Deg2Rad) * closest_distance;

            Vector3 direction = Vector3.Cross(Vector3.Cross(Normal, other.Normal), Normal).normalized;

            if (Vector3.Angle(direction, other.Normal) > 90)
                direction = -direction;

            point = closest_point + direction * distance;

            return true;
        }

        public bool Contains(Vector3 point)
        {
            Vector3 direction = (point - Center).normalized;

            // 大于0.01f表示不等于0 ，不等于0也就是不垂直
            if (Vector3.Dot(direction, Normal) > 0.01f)
                return false;

            float distance = Vector3.Distance(point, Center);
            return Mathf.Abs(distance * Vector3.Dot(direction, WidthDirection)) <= Width / 2 && Mathf.Abs(distance * Vector3.Dot(direction, HeightDirection)) <= Height / 2;
        }

        #endregion

    }

    public class OctreeBoxBounds : OctreeBounds
    {

        #region 字段

        [SerializeField]
        [Tooltip("大小")]
        private Vector3 size = Vector3.one;

        [SerializeField]
        [Tooltip("中心点")]
        private Vector3 center = Vector3.zero;

        private Bounds bounds;


        private OctreePlane plane_up = new OctreePlane();
        private OctreePlane plane_down = new OctreePlane();
        private OctreePlane plane_left = new OctreePlane();
        private OctreePlane plane_right = new OctreePlane();
        private OctreePlane plane_front = new OctreePlane();
        private OctreePlane plane_back = new OctreePlane();

        private Vector3 intersectPoint;

        internal Vector3 BottomLeftDown => Bounds.min;
        internal Vector3 BottomLeftUp => Bounds.min + new Vector3(0, 0, Bounds.size.z);
        internal Vector3 BottomRightDown => Bounds.min + new Vector3(Bounds.size.x, 0, 0);
        internal Vector3 BottomRightUp => Bounds.max - new Vector3(0, Bounds.size.y, 0);

        internal Vector3 TopLeftDown => BottomLeftDown + new Vector3(0, Bounds.size.y, 0);
        internal Vector3 TopLeftUp => BottomLeftUp + new Vector3(0, Bounds.size.y, 0);
        internal Vector3 TopRightDown => BottomRightDown + new Vector3(0, Bounds.size.y, 0);
        internal Vector3 TopRightUp => Bounds.max;

        [Tooltip("世界坐标中的边界!")]
        private Bounds world_bounds;

        #endregion

        #region 属性

        public Vector3 Size
        {
            get
            {
                return size;
            }
            set
            {
                size = value;
            }
        }

        public Vector3 Center
        {
            get
            {
                return center;
            }
            set
            {
                center = value;
            }
        }


        private Bounds Bounds
        {
            get
            {
                bounds.center = Center;
                bounds.size = Size;
                return bounds;
            }
        }


        public OctreePlane PlaneUp
        {
            get
            {
                plane_up.SetCenterAndNormal(Center + Vector3.up * Size.y / 2, Vector3.up, Size.x, Size.z, Vector3.right, Vector3.forward);
                return plane_up;
            }
        }

        public OctreePlane PlaneDown
        {
            get
            {
                plane_down.SetCenterAndNormal(Center + Vector3.down * Size.y / 2, Vector3.down, Size.x, Size.z, Vector3.right, Vector3.forward);
                return plane_down;
            }
        }

        public OctreePlane PlaneLeft
        {
            get
            {
                plane_left.SetCenterAndNormal(Center + Vector3.left * Size.x / 2, Vector3.left, Size.z, Size.y, Vector3.forward, Vector3.up);
                return plane_left;
            }
        }
        public OctreePlane PlaneRight
        {
            get
            {
                plane_right.SetCenterAndNormal(Center + Vector3.right * Size.x / 2, Vector3.right, Size.z, Size.y, Vector3.forward, Vector3.up);
                return plane_right;
            }
        }
        public OctreePlane PlaneFront
        {
            get
            {
                plane_front.SetCenterAndNormal(Center + Vector3.forward * Size.z / 2, Vector3.forward, Size.x, Size.y, Vector3.right, Vector3.up);
                return plane_front;
            }
        }
        public OctreePlane PlaneBack
        {
            get
            {
                plane_back.SetCenterAndNormal(Center + Vector3.back * Size.z / 2, Vector3.back, Size.x, Size.y, Vector3.right, Vector3.up);
                return plane_back;
            }
        }

        #endregion




#if UNITY_EDITOR

        private void OnDrawGizmos()
        {
            Gizmos.matrix = transform.localToWorldMatrix;
            Gizmos.color = Color.green;
            Gizmos.DrawWireCube(center, size);
        }

#endif

        #region 抽象方法

        public override Vector3 ClosestPoint(Vector3 point)
        {
            Vector3 p = transform.worldToLocalMatrix.MultiplyPoint(point);
            Vector3 c = Bounds.ClosestPoint(p);
            return transform.localToWorldMatrix.MultiplyPoint(c);
        }

        public override bool Contains(Vector3 point)
        {
            Vector3 p = transform.worldToLocalMatrix.MultiplyPoint(point);
            return Bounds.Contains(p);
        }

        public override bool IntersectRay(Ray ray, float distance = -1)
        {
            IntersectInfo intersect;
            return IntersectRay(ray, out intersect, distance);
        }

        public override bool IntersectRay(Ray ray, out IntersectInfo info, float distance = -1)
        {
            info = new IntersectInfo();
            info.bounds = this;
            // 起点在内部
            if (Contains(ray.origin)) return true;

            Vector3 origin_point = transform.worldToLocalMatrix.MultiplyPoint(ray.origin);
            Vector3 direction = transform.worldToLocalMatrix.MultiplyVector(ray.direction).normalized;
             
            Ray ray1 = new Ray(origin_point, direction);

            if (distance != -1)
            {
                distance = Vector3.Distance(ray1.origin, transform.worldToLocalMatrix.MultiplyPoint(ray.GetPoint(distance)));
            }


            if (PlaneUp.GetPoint(ray1, out info.point, distance))
            {
                info.point = transform.localToWorldMatrix.MultiplyPoint(info.point);
                info.normal = transform.localToWorldMatrix.MultiplyVector(PlaneUp.Normal).normalized;
                return true;
            }

            if (PlaneDown.GetPoint(ray1, out info.point, distance))
            {
                info.point = transform.localToWorldMatrix.MultiplyPoint(info.point);
                info.normal = transform.localToWorldMatrix.MultiplyVector(PlaneDown.Normal).normalized;
                return true;
            }

            if (PlaneLeft.GetPoint(ray1, out info.point, distance))
            {
                info.point = transform.localToWorldMatrix.MultiplyPoint(info.point);
                info.normal = transform.localToWorldMatrix.MultiplyVector(PlaneLeft.Normal).normalized;
                return true;
            }

            if (PlaneRight.GetPoint(ray1, out info.point, distance))
            {
                info.point = transform.localToWorldMatrix.MultiplyPoint(info.point);
                info.normal = transform.localToWorldMatrix.MultiplyVector(PlaneRight.Normal).normalized;
                return true;
            }

            if (PlaneFront.GetPoint(ray1, out info.point, distance))
            {
                info.point = transform.localToWorldMatrix.MultiplyPoint(info.point);
                info.normal = transform.localToWorldMatrix.MultiplyVector(PlaneFront.Normal).normalized;
                return true;
            }

            if (PlaneBack.GetPoint(ray1, out info.point, distance))
            {
                info.point = transform.localToWorldMatrix.MultiplyPoint(info.point);
                info.normal = transform.localToWorldMatrix.MultiplyVector( PlaneBack.Normal).normalized;
                return true;
            }


            return false;
        }

        public override bool Intersects(Bounds bounds)
        {
            // 正方体有12个边，分别用12个边来判断是否相交，只要有一个相交, 说明两个区域相交了

            Vector3 bottom_left_down = bounds.min;
            Vector3 bottom_left_up = bounds.min + new Vector3(0, 0, bounds.size.z);
            Vector3 bottom_right_down = bounds.min + new Vector3(bounds.size.x, 0, 0);
            Vector3 bottom_right_up = bounds.max - new Vector3(0, bounds.size.y, 0);

            Vector3 top_left_down = bottom_left_down + new Vector3(0, bounds.size.y, 0);
            Vector3 top_left_up = bottom_left_up + new Vector3(0, bounds.size.y, 0);
            Vector3 top_right_down = bottom_right_down + new Vector3(0, bounds.size.y, 0);
            Vector3 top_right_up = bounds.max;

            Ray ray = new Ray(bottom_left_down, (bottom_right_down - bottom_left_down).normalized);
            if (IntersectRay(ray, Vector3.Distance(bottom_right_down, bottom_left_down)))
            {
                return true;
            }
            ray.origin = bottom_right_down;
            ray.direction = (bottom_right_up - bottom_right_down).normalized;
            if (IntersectRay(ray, Vector3.Distance(bottom_right_up, bottom_right_down)))
            {
                return true;
            }

            ray.origin = bottom_right_up;
            ray.direction = (bottom_left_up - bottom_right_up).normalized;
            if (IntersectRay(ray, Vector3.Distance(bottom_left_up, bottom_right_up)))
            {
                return true;
            }

            ray.origin = bottom_left_up;
            ray.direction = (bottom_left_down - bottom_left_up).normalized;
            if (IntersectRay(ray, Vector3.Distance(bottom_left_down, bottom_left_up)))
            {
                return true;
            }


            ray.origin = top_left_down;
            ray.direction = (top_right_down - top_left_down).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_right_down, top_left_down)))
            {
                return true;
            }


            ray.origin = top_right_down;
            ray.direction = (top_right_up - top_right_down).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_right_up, top_right_down)))
            {
                return true;
            }

            ray.origin = top_right_up;
            ray.direction = (top_left_up - top_right_up).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_left_up, top_right_up)))
            {
                return true;
            }

            ray.origin = top_left_up;
            ray.direction = (top_left_down - top_left_up).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_left_down, top_left_up)))
            {
                return true;
            }


            ray.origin = bottom_left_down;
            ray.direction = (top_left_down - bottom_left_down).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_left_down, bottom_left_down)))
            {
                return true;
            }

            ray.origin = bottom_left_up;
            ray.direction = (top_left_up - bottom_left_up).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_left_up, bottom_left_up)))
            {
                return true;
            }

            ray.origin = bottom_right_down;
            ray.direction = (top_right_down - bottom_right_down).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_right_down, bottom_right_down)))
            {
                return true;
            }

            ray.origin = bottom_right_up;
            ray.direction = (top_right_up - bottom_right_up).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_right_up, bottom_right_up)))
            {
                return true;
            }

            // 计算


            Vector3 box_bottom_left_down = transform.localToWorldMatrix.MultiplyPoint(BottomLeftDown);
            Vector3 box_bottom_left_up = transform.localToWorldMatrix.MultiplyPoint(BottomLeftUp);
            Vector3 box_bottom_right_down = transform.localToWorldMatrix.MultiplyPoint(BottomRightDown);
            Vector3 box_bottom_right_up = transform.localToWorldMatrix.MultiplyPoint(BottomRightUp);

            Vector3 box_top_left_down = transform.localToWorldMatrix.MultiplyPoint(TopLeftDown);
            Vector3 box_top_left_up = transform.localToWorldMatrix.MultiplyPoint(TopLeftUp);
            Vector3 box_top_right_down = transform.localToWorldMatrix.MultiplyPoint(TopRightDown);
            Vector3 box_top_right_up = transform.localToWorldMatrix.MultiplyPoint(TopRightUp);


            float distance;

            ray.origin = box_bottom_left_down;
            ray.direction = (box_bottom_right_down - box_bottom_left_down).normalized;
            if (bounds.IntersectRay(ray, out distance))
            {
                if (Vector3.Distance(box_bottom_right_down, box_bottom_left_down) >= distance)
                    return true;
            }


            ray.origin = box_bottom_right_down;
            ray.direction = (box_bottom_right_up - box_bottom_right_down).normalized;
            if (bounds.IntersectRay(ray, out distance))
            {
                if (Vector3.Distance(box_bottom_right_up, box_bottom_right_down) >= distance)
                    return true;
            }

            ray.origin = box_bottom_right_up;
            ray.direction = (box_bottom_left_up - box_bottom_right_up).normalized;
            if (bounds.IntersectRay(ray, out distance))
            {
                if (Vector3.Distance(box_bottom_left_up, box_bottom_right_up) >= distance)
                    return true;
            }

            ray.origin = box_bottom_left_up;
            ray.direction = (box_bottom_left_down - box_bottom_left_up).normalized;
            if (bounds.IntersectRay(ray, out distance))
            {
                if (Vector3.Distance(box_bottom_left_down, box_bottom_left_up) >= distance)
                    return true;
            }


            ray.origin = box_top_left_down;
            ray.direction = (box_top_right_down - box_top_left_down).normalized;
            if (bounds.IntersectRay(ray, out distance))
            {
                if (Vector3.Distance(box_top_right_down, box_top_left_down) >= distance)
                    return true;
            }


            ray.origin = box_top_right_down;
            ray.direction = (box_top_right_up - box_top_right_down).normalized;
            if (bounds.IntersectRay(ray, out distance))
            {
                if (Vector3.Distance(box_top_right_up, box_top_right_down) >= distance)
                    return true;
            }

            ray.origin = box_top_right_up;
            ray.direction = (box_top_left_up - box_top_right_up).normalized;
            if (bounds.IntersectRay(ray, out distance))
            {
                if (Vector3.Distance(box_top_left_up, box_top_right_up) >= distance)
                    return true;
            }

            ray.origin = box_top_left_up;
            ray.direction = (box_top_left_down - box_top_left_up).normalized;
            if (bounds.IntersectRay(ray, out distance))
            {
                if (Vector3.Distance(box_top_left_down, box_top_left_up) >= distance)
                    return true;
            }


            ray.origin = box_bottom_left_down;
            ray.direction = (box_top_left_down - box_bottom_left_down).normalized;
            if (bounds.IntersectRay(ray, out distance))
            {
                if (Vector3.Distance(box_top_left_down, box_bottom_left_down) >= distance)
                    return true;
            }

            ray.origin = box_bottom_left_up;
            ray.direction = (box_top_left_up - box_bottom_left_up).normalized;
            if (bounds.IntersectRay(ray, out distance))
            {
                if (Vector3.Distance(box_top_left_up, box_bottom_left_up) >= distance)
                    return true;
            }

            ray.origin = box_bottom_right_down;
            ray.direction = (box_top_right_down - box_bottom_right_down).normalized;
            if (bounds.IntersectRay(ray, out distance))
            {
                if (Vector3.Distance(box_top_right_down, box_bottom_right_down) >= distance)
                    return true;
            }

            ray.origin = box_bottom_right_up;
            ray.direction = (box_top_right_up - box_bottom_right_up).normalized;
            if (bounds.IntersectRay(ray, out distance))
            {
                if (Vector3.Distance(box_top_right_up, box_bottom_right_up) >= distance)
                    return true;
            }


            return false;
        }

        public override bool Intersects(OctreeBounds other)
        {
            if (other is OctreeBoxBounds)
            {
                return IntersectsWithBoxBounds(other as OctreeBoxBounds);
            }
            else if (other is OctreeSphereBounds)
            {
                OctreeSphereBounds sphere = other as OctreeSphereBounds;
                return sphere.Intersects(this);
            }
            else if (other is OctreeCylinderBounds)
            {
                OctreeCylinderBounds cylinder = other as OctreeCylinderBounds;
                return cylinder.Intersects(this);
            }

            return false;
        }

        #endregion


        #region 方法

        internal bool IntersectsWithBoxBounds(OctreeBoxBounds other)
        {
            if (IntersectsWithBoxBoundsDirect(other))
                return true;


            if (other.IntersectsWithBoxBoundsDirect(this))
                return true;

            return false;
        }

        internal bool IntersectsWithBoxBoundsDirect(OctreeBoxBounds other)
        {
            Vector3 bottom_left_down = other.transform.localToWorldMatrix.MultiplyPoint(other.BottomLeftDown);
            Vector3 bottom_left_up = other.transform.localToWorldMatrix.MultiplyPoint(other.BottomLeftUp);
            Vector3 bottom_right_down = other.transform.localToWorldMatrix.MultiplyPoint(other.BottomRightDown);
            Vector3 bottom_right_up = other.transform.localToWorldMatrix.MultiplyPoint(other.BottomRightUp);

            Vector3 top_left_down = other.transform.localToWorldMatrix.MultiplyPoint(other.TopLeftDown);
            Vector3 top_left_up = other.transform.localToWorldMatrix.MultiplyPoint(other.TopLeftUp);
            Vector3 top_right_down = other.transform.localToWorldMatrix.MultiplyPoint(other.TopRightDown);
            Vector3 top_right_up = other.transform.localToWorldMatrix.MultiplyPoint(other.TopRightUp);

            Ray ray = new Ray(bottom_left_down, (bottom_right_down - bottom_left_down).normalized);
            if (IntersectRay(ray, Vector3.Distance(bottom_right_down, bottom_left_down)))
            {
                return true;
            }
            ray.origin = bottom_right_down;
            ray.direction = (bottom_right_up - bottom_right_down).normalized;
            if (IntersectRay(ray, Vector3.Distance(bottom_right_up, bottom_right_down)))
            {
                return true;
            }

            ray.origin = bottom_right_up;
            ray.direction = (bottom_left_up - bottom_right_up).normalized;
            if (IntersectRay(ray, Vector3.Distance(bottom_left_up, bottom_right_up)))
            {
                return true;
            }

            ray.origin = bottom_left_up;
            ray.direction = (bottom_left_down - bottom_left_up).normalized;
            if (IntersectRay(ray, Vector3.Distance(bottom_left_down, bottom_left_up)))
            {
                return true;
            }


            ray.origin = top_left_down;
            ray.direction = (top_right_down - top_left_down).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_right_down, top_left_down)))
            {
                return true;
            }


            ray.origin = top_right_down;
            ray.direction = (top_right_up - top_right_down).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_right_up, top_right_down)))
            {
                return true;
            }

            ray.origin = top_right_up;
            ray.direction = (top_left_up - top_right_up).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_left_up, top_right_up)))
            {
                return true;
            }

            ray.origin = top_left_up;
            ray.direction = (top_left_down - top_left_up).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_left_down, top_left_up)))
            {
                return true;
            }


            ray.origin = bottom_left_down;
            ray.direction = (top_left_down - bottom_left_down).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_left_down, bottom_left_down)))
            {
                return true;
            }

            ray.origin = bottom_left_up;
            ray.direction = (top_left_up - bottom_left_up).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_left_up, bottom_left_up)))
            {
                return true;
            }

            ray.origin = bottom_right_down;
            ray.direction = (top_right_down - bottom_right_down).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_right_down, bottom_right_down)))
            {
                return true;
            }

            ray.origin = bottom_right_up;
            ray.direction = (top_right_up - bottom_right_up).normalized;
            if (IntersectRay(ray, Vector3.Distance(top_right_up, bottom_right_up)))
            {
                return true;
            }
            return false;
        }

        public override Bounds GetBounds()
        {
            world_bounds.center = transform.localToWorldMatrix.MultiplyPoint(Center);
            world_bounds.size = Vector3.zero;

           Vector3 bottom_left_down = transform.localToWorldMatrix.MultiplyPoint(BottomLeftDown);
            Vector3 bottom_left_up = transform.localToWorldMatrix.MultiplyPoint(BottomLeftUp);
            Vector3 bottom_right_down = transform.localToWorldMatrix.MultiplyPoint(BottomRightDown);
            Vector3 bottom_right_up = transform.localToWorldMatrix.MultiplyPoint(BottomRightUp);

            Vector3 top_left_down = transform.localToWorldMatrix.MultiplyPoint(TopLeftDown);
            Vector3 top_left_up = transform.localToWorldMatrix.MultiplyPoint(TopLeftUp);
            Vector3 top_right_down = transform.localToWorldMatrix.MultiplyPoint(TopRightDown);
            Vector3 top_right_up = transform.localToWorldMatrix.MultiplyPoint(TopRightUp);

            world_bounds.Encapsulate(bottom_left_down);
            world_bounds.Encapsulate(bottom_left_up);
            world_bounds.Encapsulate(bottom_right_down);
            world_bounds.Encapsulate(bottom_right_up);

            world_bounds.Encapsulate(top_left_down);
            world_bounds.Encapsulate(top_left_up);
            world_bounds.Encapsulate(top_right_down);
            world_bounds.Encapsulate(top_right_up);
            return world_bounds;
        }
         
        #endregion

    }

}

